#include "syntax_parser.h"
#include "errors_warnings.h"

#include "main_container.h"
extern MainContainer * CompilerData;

// <generate_transactions> ~ <name> ( <trans_list> )  {NAME}
// <generate_transactions> ~ <name>  {NAME}
// <generate_transactions> ~ ? {after, every, ;, send}
void Parser::Parse_GenerateTransactions(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_GenerateTransactions");
#endif

	LexicUnit currentUnit;
#ifdef TRACE
	CompilerData->LogTrace->ReportLine("Getting lexic unit.");
#endif
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	// if current lexic unit is in the select set of {NAME}
	if(currentUnit.type == LUTypeIdentifier)
	{
		// process nonterminal symbol <name> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_Name(newNode0);

		// get current lexic unit
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		// if current lexic unit is {(} chouse production <generate_transactions> ~ <name> ( <trans_list> )  {NAME}
		if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftParenthesis)
		{
			// write type of production in this node
			parent->Production = Gr_GenerateTransactions__Name_spLPar_TransList_spRPar;

			// process terminal symbol '(' 
			SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode1);
			newNode1->LexUnitID=this->CurrentLexicPosition;
			newNode1->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
			
			// process nonterminal symbol <trans_list> 
			SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode2);
			Parse_TransList(newNode2);

			// process terminal symbol ')' 
			currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
			if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightParenthesis)
			{
				SyntaxTreeNode * newNode3 = new SyntaxTreeNode();
				parent->Nodes->Add(newNode3);
				newNode3->LexUnitID=this->CurrentLexicPosition;
				newNode3->Production=Gr_Terminal;
				//increase counter
				CurrentLexicPosition++;
			}
			else
			{
				//report syntactic error
				CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_RIGHT_PARENTHESIS_MATCH);
				//increase counter
				CurrentLexicPosition++;
			}
		}
		// else chouse production <generate_transactions> ~ <name>  {NAME}
		else
		{
			// write type of production in this node
			parent->Production = Gr_GenerateTransactions__Name;

		}
	}
	// if current lexic unit is in the select set of {after, every, ;, send}
	else if((currentUnit.type == LUTypeKeyword && (currentUnit.subtype == KeywordAfter || currentUnit.subtype == KeywordEvery
		|| currentUnit.subtype == KeywordSend))
		|| (currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterSemicolon))
	{
		// this is epsilon part of production
		parent->Production = Gr_GenerateTransactions__epsilon;
		// new node is not needed
		// there are no symbols on the right side of this production
		// so that all

	}
	else
	{
		// ERROR has been found
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_GENERATE_TRANSACTIONS_BEGINING);
		// MAKE LOGICAL RECOVERING
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_GenerateTransactions");
#endif
}


// <terminate_block> ~ terminate <expression> ;  {terminate}
// <terminate_block> ~ terminate ;  {terminate}
void Parser::Parse_TerminateBlock(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_TerminateBlock");
#endif
	
	LexicUnit currentUnit;

#ifdef TRACE
	CompilerData->LogTrace->ReportLine("Getting lexic unit.");
#endif
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	// if current lexic unit is in the select set of {terminate}
	if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordTerminate)
	{
		// process terminal symbol 'terminate' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		// get current lexic unit
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		// if current lexic unit is {;} chouse production <terminate_block> ~ terminate ;  {terminate}
		if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterSemicolon)
		{
			// write type of production in this node
			parent->Production = Gr_TerminateBlock__terminate_spSemiCol;

			// process terminal symbol ';' 
			SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode1);
			newNode1->LexUnitID=this->CurrentLexicPosition;
			newNode1->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;

		}
		// else chouse production <terminate_block> ~ terminate <expression> ;  {terminate}
		else
		{
			// write type of production in this node
			parent->Production = Gr_TerminateBlock__terminate_Expression_spSemiCol;

			// process nonterminal symbol <expression> 
			SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode1);
			Parse_Expression(newNode1);

			// process terminal symbol ';' 
			currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
			if( currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterSemicolon)
			{
				SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
				parent->Nodes->Add(newNode2);
				newNode2->LexUnitID=this->CurrentLexicPosition;
				newNode2->Production=Gr_Terminal;
				//increase counter
				CurrentLexicPosition++;
			}
			else
			{
				//report syntactic error
				CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_SEMICOLON_MATCH);
				//increase counter
				CurrentLexicPosition++;
			}
		}
	}
	else
	{
		// ERROR has been found
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_TERMINATE_BLOCK_BEGINING);
		// MAKE LOGICAL RECOVERING
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_TerminateBlock");
#endif
}


// <units_in_expression> ~ <expression> units in  {!, -, +, (, LITERAL, null, new, NAME}
// <units_in_expression> ~ ? {!, -, +, (, LITERAL, null, new, NAME}
void Parser::Parse_UnitsInExpression(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_UnitsInExpression");
#endif

	LexicUnit currentUnit;

	int lexicPosition = this->CurrentLexicPosition;
	int chouseProduction = -1;
	
	do
	{
		#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Getting lexic unit.");
		#endif
		
		// get lexic unit
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

		// if lexic unit is endOfFile
		if(currentUnit.type == LUTypeSpecialType && currentUnit.subtype == endOfFile)
		{
			break;
		}
		// if lexic unit is {units}
		else if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordUnits)
		{
			chouseProduction = 0;
			break;
		}
		// if lexic unit is {;, forming}
		else if((currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterSemicolon)
			|| (currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordForming))
		{
			chouseProduction = 1;
			break;
		}
		
		this->CurrentLexicPosition++;
	}
	while(1);

	// get lexic position
	this->CurrentLexicPosition = lexicPosition;
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	if(chouseProduction == 0)
	{
		// if current lexic unit is in the select set of {!, -, +, (, LITERAL, null, new, NAME}
		if((currentUnit.type == LUTypeOperator && (currentUnit.subtype == OperatorNot || currentUnit.subtype == OperatorSubtraction || currentUnit.subtype == OperatorAddition))
			|| (currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftParenthesis)
			|| (currentUnit.type == LUTypeConstantBool || currentUnit.type == LUTypeConstantFloat || currentUnit.type == LUTypeConstantInteger)
			|| (currentUnit.type == LUTypeKeyword && (currentUnit.subtype == KeywordNull || currentUnit.subtype == KeywordNew))
			|| (currentUnit.type == LUTypeIdentifier))
		{
			// write type of production in this node
			parent->Production = Gr_UnitsInExpression__Expression_units_in;

			// process nonterminal symbol <expression> 
			SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode0);
			Parse_Expression(newNode0);

			// process terminal symbol 'units' 
			currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
			if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordUnits)
			{
				SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
				parent->Nodes->Add(newNode1);
				newNode1->LexUnitID=this->CurrentLexicPosition;
				newNode1->Production=Gr_Terminal;
				//increase counter
				CurrentLexicPosition++;
			}
			else
			{
				//report syntactic error
				CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_UNITS_MATCH);
				//increase counter
				CurrentLexicPosition++;
			}

			// process terminal symbol 'in' 
			currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
			if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordIn)
			{
				SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
				parent->Nodes->Add(newNode2);
				newNode2->LexUnitID=this->CurrentLexicPosition;
				newNode2->Production=Gr_Terminal;
				//increase counter
				CurrentLexicPosition++;
			}
			else
			{
				//report syntactic error  
				CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_IN_MATCH);
				//increase counter
				CurrentLexicPosition++;
			}
		}
		else
		{
			// ERROR has been found
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_UNITS_IN_EXPRESSION_BEGINING);
			// MAKE LOGICAL RECOVERING
		}
	}
	else if(chouseProduction == 1)
	{
		// if current lexic unit is in the select set of {!, -, +, (, LITERAL, null, new, NAME}
		if((currentUnit.type == LUTypeOperator && (currentUnit.subtype == OperatorNot || currentUnit.subtype == OperatorSubtraction || currentUnit.subtype == OperatorAddition))
			|| (currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftParenthesis)
			|| (currentUnit.type == LUTypeConstantBool || currentUnit.type == LUTypeConstantFloat || currentUnit.type == LUTypeConstantInteger)
			|| (currentUnit.type == LUTypeKeyword && (currentUnit.subtype == KeywordNull || currentUnit.subtype == KeywordNew))
			|| (currentUnit.type == LUTypeIdentifier))
		{
			// this is epsilon part of production
			parent->Production = Gr_UnitsInExpression__epsilon;
			// new node is not needed
			// there are no symbols on the right side of this production
			// so that all
		}
		else
		{
			// ERROR has been found
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_UNITS_IN_EXPRESSION_BEGINING);
			// MAKE LOGICAL RECOVERING
		}
	}
	else
	{
		// ERROR has been found
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_UNITS_IN_EXPRESSION_BEGINING);
		// MAKE LOGICAL RECOVERING
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_UnitsInExpression");
#endif
}



// <units_from_expression> ~ <expression> units from  {!, -, +, (, LITERAL, null, new, NAME}
// <units_from_expression> ~ ? {!, -, +, (, LITERAL, null, new, NAME}
void Parser::Parse_UnitsFromExpression(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_UnitsFromExpression");
#endif

	LexicUnit currentUnit;
	int lexicPosition = this->CurrentLexicPosition;
	int chouseProduction = -1;
	
	do
	{
		#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Getting lexic unit.");
		#endif
		// get lexic unit
		currentUnit = CompilerData->Units->GetLexicUnit(lexicPosition);

		if(currentUnit.type == LUTypeSpecialType && currentUnit.subtype == endOfFile)
		{
			break;
		}

		else if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordUnits)
		{
			chouseProduction = 0;
			break;
		}
		else if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterSemicolon)
		{
			chouseProduction = 1;
			break;
		}

		lexicPosition++;
	}
	while(1);

	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	if(chouseProduction == 0)
	{
		// if current lexic unit is in the select set of {!, -, +, (, LITERAL, null, new, NAME}
		if((currentUnit.type == LUTypeOperator && (currentUnit.subtype == OperatorNot || currentUnit.subtype == OperatorSubtraction || currentUnit.subtype == OperatorAddition))
			|| (currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftParenthesis)
			|| (currentUnit.type == LUTypeConstantBool || currentUnit.type == LUTypeConstantFloat || currentUnit.type == LUTypeConstantInteger)
			|| (currentUnit.type == LUTypeKeyword && (currentUnit.subtype == KeywordNull || currentUnit.subtype == KeywordNew))
			|| (currentUnit.type == LUTypeIdentifier))
		{
			// write type of production in this node
			parent->Production = Gr_UnitsFromExpression__Expression_units_from;
			
			// process nonterminal symbol <expression> 
			SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode0);
			Parse_Expression(newNode0);

			// process terminal symbol 'units' 
			currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
			if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordUnits)
			{
				SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
				parent->Nodes->Add(newNode1);
				newNode1->LexUnitID=this->CurrentLexicPosition;
				newNode1->Production=Gr_Terminal;
				//increase counter
				CurrentLexicPosition++;
			}
			else
			{
				//report syntactic error
				CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_UNITS_MATCH);
				//increase counter
				CurrentLexicPosition++;
			}

			// process terminal symbol 'from' 
			currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
			if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordFrom)
			{
				SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
				parent->Nodes->Add(newNode2);
				newNode2->LexUnitID=this->CurrentLexicPosition;
				newNode2->Production=Gr_Terminal;
				//increase counter
				CurrentLexicPosition++;
			}
			else
			{
				//report syntactic error 
				CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_FROM_MATCH);
				//increase counter
				CurrentLexicPosition++;
			}

		}
		else
		{
			// ERROR has been found
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_UNITS_FROM_EXPRESSION_BEGINING);
			// MAKE LOGICAL RECOVERING
		}
	}
	else if(chouseProduction == 1)
	{
		// if current lexic unit is in the select set of {!, -, +, (, LITERAL, null, new, NAME}
		if((currentUnit.type == LUTypeOperator && (currentUnit.subtype == OperatorNot || currentUnit.subtype == OperatorSubtraction || currentUnit.subtype == OperatorAddition))
			|| (currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftParenthesis)
			|| (currentUnit.type == LUTypeConstantBool || currentUnit.type == LUTypeConstantFloat || currentUnit.type == LUTypeConstantInteger)
			|| (currentUnit.type == LUTypeKeyword && (currentUnit.subtype == KeywordNull || currentUnit.subtype == KeywordNew))
			|| (currentUnit.type == LUTypeIdentifier))
		{
			// this is epsilon part of production
			parent->Production = Gr_UnitsFromExpression__epsilon;
			// new node is not needed
			// there are no symbols on the right side of this production
			// so that all
		}
		else
		{
			// ERROR has been found
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_UNITS_FROM_EXPRESSION_BEGINING);
			// MAKE LOGICAL RECOVERING
		}
	}
	else
	{
		// ERROR has been found
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_UNITS_FROM_EXPRESSION_BEGINING);
		// MAKE LOGICAL RECOVERING
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_UnitsFromExpression");
#endif
}

// <timeout> ~ timeout <expression>  {timeout}
// <timeout> ~ timeout <expression> { <model_structure> }  {timeout}
// <timeout> ~ ? {;}
void Parser::Parse_Timeout(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_Timeout");
#endif

	LexicUnit currentUnit;
#ifdef TRACE
	CompilerData->LogTrace->ReportLine("Getting lexic unit.");
#endif
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	// if current lexic unit is in the select set of {timeout}
	if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordTimeout)
	{
		// process terminal symbol 'timeout' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		// process nonterminal symbol <expression> 
		SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode1);
		Parse_Expression(newNode1);

		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftCurlyBrace)
		{
			// write type of production in this node
			parent->Production = Gr_Timeout__timeout_Expression_spLCBrac_ModelStructure_spRCBrac;
			
			// process terminal symbol '{' 
			SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode2);
			newNode2->LexUnitID=this->CurrentLexicPosition;
			newNode2->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		
			// process nonterminal symbol <model_structure> 
			SyntaxTreeNode * newNode3 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode3);
			Parse_ModelStructure(newNode3);

			// process terminal symbol '}' 
			currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
			if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightCurlyBrace)
			{
				SyntaxTreeNode * newNode4 = new SyntaxTreeNode();
				parent->Nodes->Add(newNode4);
				newNode4->LexUnitID=this->CurrentLexicPosition;
				newNode4->Production=Gr_Terminal;
				//increase counter
				CurrentLexicPosition++;
			}
			else
			{
				//report syntactic error
				CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_RIGHT_CURLY_BRACE_MATCH);
				//increase counter
				CurrentLexicPosition++;
			}

		}
		else
		{
			// write type of production in this node
			parent->Production = Gr_Timeout__timeout_Expression;
		}

	}
	// if current lexic unit is in the select set of {;}
	else if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterSemicolon)
	{
		// this is epsilon part of production
		parent->Production = Gr_Timeout__epsilon;
		// new node is not needed
		// there are no symbols on the right side of this production
		// so that all
	}
	else
	{
		// ERROR has been found
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_TIMEOUT_BEGINING);
		// MAKE LOGICAL RECOVERING
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_Timeout");
#endif
}



// <gather_block> ~ gather <and_destroy> <expression> ;  {gather}
// <gather_block> ~ gather <and_destroy> ;  {gather}
void Parser::Parse_GatherBlock(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_GatherBlock");
#endif

	LexicUnit currentUnit;

#ifdef TRACE
	CompilerData->LogTrace->ReportLine("Getting lexic unit.");
#endif
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	// if current lexic unit is in the select set of {gather}
	if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordGather)
	{
		// process terminal symbol 'gather' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		// process nonterminal symbol <and_destroy> 
		SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode1);
		Parse_AndDestroy(newNode1);

		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		
		if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterSemicolon)
		{
			// write type of production in this node
			parent->Production = Gr_GatherBlock__gather_AndDestroy_spSemiCol;

			// process terminal symbol ';' 
			SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode2);
			newNode2->LexUnitID=this->CurrentLexicPosition;
			newNode2->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			// write type of production in this node
			parent->Production = Gr_GatherBlock__gather_AndDestroy_Expression_spSemiCol;
			
			// process nonterminal symbol <expression> 
			SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode2);
			Parse_Expression(newNode2);

			// process terminal symbol ';' 
			currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
			if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterSemicolon)
			{
				SyntaxTreeNode * newNode3 = new SyntaxTreeNode();
				parent->Nodes->Add(newNode3);
				newNode3->LexUnitID=this->CurrentLexicPosition;
				newNode3->Production=Gr_Terminal;
				//increase counter
				CurrentLexicPosition++;
			}
			else
			{
				//report syntactic error
				CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_SEMICOLON_MATCH);
				//increase counter
				CurrentLexicPosition++;
			}

		}
	}
	else
	{
		// ERROR has been found
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_GATHER_BLOCK_BEGINING);
		// MAKE LOGICAL RECOVERING
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_GatherBlock");
#endif
}


// <sim_run> ~ run <expression> simulations <upto_expression> ;  {run}
// <sim_run> ~ run <upto_expression> ;  {run}
void Parser::Parse_SimRun(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_SimRun");
#endif

	LexicUnit currentUnit;
	int lexicPosition;
	int chouseProduction = -1;
#ifdef TRACE
	CompilerData->LogTrace->ReportLine("Getting lexic unit.");
#endif	
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordRun) 
	{

		// process terminal symbol 'run' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		lexicPosition = this->CurrentLexicPosition;
		do
		{
			// get lexic unit
			currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

			if(currentUnit.type == LUTypeSpecialType && currentUnit.subtype == endOfFile)
			{
				break;
			}
			else if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordSimulations)
			{
				chouseProduction = 0;
				break;
			}
			else if((currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterSemicolon)
				|| (currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordUpto))
			{
				chouseProduction = 1;
				break;
			}
			
			this->CurrentLexicPosition++;
		}
		while(1);

		this->CurrentLexicPosition = lexicPosition;

		if(chouseProduction == 0)
		{
			// write type of production in this node
			parent->Production = Gr_SimRun__run_Expression_simulations_UptoExpression_spSemiCol;

			// process nonterminal symbol <expression> 
			SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode1);
			Parse_Expression(newNode1);

			// process terminal symbol 'simulations' 
			currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
			if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordSimulations)
			{
				SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
				parent->Nodes->Add(newNode2);
				newNode2->LexUnitID=this->CurrentLexicPosition;
				newNode2->Production=Gr_Terminal;
				//increase counter
				CurrentLexicPosition++;
			}
			else
			{
				//report syntactic error
				CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_SIMULATIONS_MATCH);
				//increase counter
				CurrentLexicPosition++;
			}

			// process nonterminal symbol <upto_expression> 
			SyntaxTreeNode * newNode3 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode3);
			Parse_UptoExpression(newNode3);

			// process terminal symbol ';' 
			currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
			if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterSemicolon)
			{
				SyntaxTreeNode * newNode4 = new SyntaxTreeNode();
				parent->Nodes->Add(newNode4);
				newNode4->LexUnitID=this->CurrentLexicPosition;
				newNode4->Production=Gr_Terminal;
				//increase counter
				CurrentLexicPosition++;
			}
			else
			{
				//report syntactic error
				CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_SEMICOLON_MATCH);
				//increase counter
				CurrentLexicPosition++;
			}

		}
		else if(chouseProduction == 1)
		{
			// write type of production in this node
			parent->Production = Gr_SimRun__run_UptoExpression_spSemiCol;

			// process nonterminal symbol <upto_expression> 
			SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode1);
			Parse_UptoExpression(newNode1);

			// process terminal symbol ';' 
			currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
			if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterSemicolon)
			{
				SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
				parent->Nodes->Add(newNode2);
				newNode2->LexUnitID=this->CurrentLexicPosition;
				newNode2->Production=Gr_Terminal;
				//increase counter
				CurrentLexicPosition++;
			}
			else
			{
				//report syntactic error
				CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_SEMICOLON_MATCH);
				//increase counter
				CurrentLexicPosition++;
			}

		}
		else
		{
			// ERROR has been found
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_SIM_RUN_BEGINING);
			// MAKE LOGICAL RECOVERING
		}
	}


	else
	{
		// ERROR has been found
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_SIM_RUN_BEGINING);
		// MAKE LOGICAL RECOVERING
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_SimRun");
#endif
}

//void Parser::Parse_TransList(SyntaxTreeNode * parent)
//{
//}


//void Parser::Parse_UptoExpression(SyntaxTreeNode * parent)
//{
//}